package com.base.system.base.init;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import com.base.system.annotation.HasPre;
import com.base.system.enums.HttpStatus;
import com.base.system.exception.HttpException;
import com.base.system.jpa.entity.JpaPermission;
import com.base.system.jpa.repository.PermissionRepository;
import com.base.system.mybatisPlus.entity.MybatisPermission;
import com.base.system.mybatisPlus.mapper.PermissionMapper;
import com.base.system.service.PermissionService;
import com.base.system.util.PackageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Order(3)
@Slf4j
@Component
public class PermissionConfigureInit implements CommandLineRunner {
    @Autowired
    private PermissionRepository permissionRepository;
    @Autowired
    private PermissionMapper permissionMapper;
    @Value(value = "${annotation.controller-path}")
    private String path;
    @Autowired
    private PermissionService permissionService;
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void run(String... args) throws Exception {
        List<JpaPermission> permissionList = new LinkedList<>();
        getAnnoData(permissionList);
        List<JpaPermission> jpaPermissions = permissionService.SaveBatch(permissionList);
        if(CollUtil.isNotEmpty(jpaPermissions)){
            for (JpaPermission saveBatch : jpaPermissions) {
                System.err.println("新增权限："+saveBatch.getPerkey());
            }
        }
    }

    private void getAnnoData(List<JpaPermission> permissionList) throws IOException, ClassNotFoundException {
        Set<String> classStr = PackageUtil.getClassStr(path);
        for (String s : classStr) {
            //获取类上的
            Class clazz = Class.forName(s);
            PreAuthorize classAnno = (PreAuthorize) clazz.getAnnotation(PreAuthorize.class);
            if(classAnno!=null){
                permissionList.add(setPermission(classAnno,s));
            }
            //获取方法上的
            Method[] allMethods = clazz.getDeclaredMethods();
            for(int i=0;i<allMethods.length;i++){
                if(allMethods[i].isAnnotationPresent(PreAuthorize.class)) {
                    PreAuthorize methodAnno = allMethods[i].getAnnotation(PreAuthorize.class);
                    if(methodAnno!=null){
                        permissionList.add(setPermission(methodAnno,s));
                    }
                }
            }
        }
    }

    private JpaPermission setPermission(PreAuthorize classAnno,String clazzName) {
        String pattern = "^hasAuthority\\([\'\"]([a-zA-Z_0-9]+)[\'\"]\\)$";
        Pattern r = Pattern.compile(pattern);
        Matcher matcher = r.matcher(classAnno.value());
        if(!matcher.matches()){
            throw new HttpException(HttpStatus.format_error,"本系统中@PreAuthorize()内容只允许定义单个格式为@PreAuthorize(\"hasAuthority('xxx_xxx')\")的格式=>位置:"+clazzName);
        }

        return new JpaPermission().setPerkey(matcher.group(1)).setNameZh("名称未定义").setNote("系统自定义权限");
    }
}
